use std::{fmt, io::Write};

use crate::{vulkan::vk_utils::utils_time::get_formatted_time, LOG_FILE};

#[derive(PartialEq)]
pub enum LogType {
    Verbose,
    Info   ,
    Debug  ,
    Warning,
    Error  ,
    Panic
}

#[inline]
pub(crate) fn write_log(args: fmt::Arguments, file_name: &str, line_number: &u32, log_type: LogType) {
    let formatted_time = get_formatted_time("%y-%m-%d %H:%M:%S%.3f");
    
    let output = match log_type {
        LogType::Verbose => format!("[{formatted_time}][Verbose]    {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
        LogType::Info    => format!("[{formatted_time}][Info]       {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
        LogType::Debug   => format!("[{formatted_time}][Debug]      {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
        LogType::Warning => format!("[{formatted_time}][Warning]    {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
        LogType::Error   => format!("[{formatted_time}][Error]      {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
        LogType::Panic   => format!("[{formatted_time}][Panic]      {:180}        {}:{}\n", format!("{}", args), file_name, line_number),
    };
    print!("{}", output);

    unsafe { 
        if LOG_FILE.is_none() {
            return
        }
        let _ = LOG_FILE.as_ref().unwrap().write(output.as_bytes());
    }
}

#[macro_export]
macro_rules! VK_LOG {
    ($log_type: expr, $($arg:tt)+) => {
        crate::vulkan::vk_utils::utils_log::write_log(
            format_args!($($arg)+),
            &file!(), &line!(),
            $log_type
        )
    };
}

#[macro_export(local_inner_macros)]
macro_rules! VK_LOGV {
    ($($arg:tt)+) => {
        VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Verbose, $($arg)+)
    };
}

#[macro_export(local_inner_macros)]
macro_rules! VK_LOGI {
    ($($arg:tt)+) => {
        VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Info, $($arg)+)
    };
}

#[macro_export(local_inner_macros)]
macro_rules! VK_LOGD {
    ($($arg:tt)+) => {
        VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Debug, $($arg)+)
    };
}

#[macro_export(local_inner_macros)]
macro_rules! VK_LOGW {
    ($($arg:tt)+) => {
        VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Warning, $($arg)+)
    };
}

#[macro_export(local_inner_macros)]
macro_rules! VK_LOGE {
    ($($arg:tt)+) => {
        VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Error, $($arg)+)
    };
}

#[macro_export]
macro_rules! VK_LOGP {
    ($($arg:tt)+) => {{
        crate::VK_LOG!($crate::vulkan::vk_utils::utils_log::LogType::Panic, $($arg)+);
        panic!()
    }}
}